import poser, os, sys, re, string
os.chdir(os.path.dirname(poser.AppLocation()))

sys.path.append( os.path.join("Runtime","Python","PoseWorks","GlowWorm","Data"))

def QuickDecompress(file):
	import gzip
	zfi = gzip.open(file)
	r = zfi.read()
	zfi.close()
	return r

def getRenderableMaterials(scene):
	renderMats = []
	for actor in scene.Actors():
		if actor.IsProp():
			if not actor.Parent().InternalName() != "UNIVERSE": pass
			elif not actor.VisibleInRender(): pass
			elif actor.IsBase(): pass
			elif actor.IsDeformer(): pass
			elif actor.IsZone(): pass
			elif re.search("CenterOf", actor.InternalName(), re.I): pass
			else:
				for mat in actor.Materials():
					renderMats.append(mat)
	for figure in scene.Figures():
		if not figure.Visible(): pass
		else:
			for mat in figure.Materials():
				renderMats.append(mat)
	return renderMats

def LoadFX6OnScene(openpath, scene):
	renderMats = getRenderableMaterials(scene)
	LoadFX6File(openpath, renderMats)

def LoadFX6File(openpath, for_mats):
	if not os.path.exists(openpath):
		raise ("Bad partial shader path.", openpath)
	dict = eval(string.strip(QuickDecompress(openpath)))
	for mat in for_mats:
		ProcessEffectDict(mat.ShaderTree(), dict)
		removeExcess(mat)

def Stitch(st, nodeTable, psInput, inputDict):
	stitchTuple = HasStitch(inputDict)
	stitchNode = psInput.InNode()
	if stitchNode and stitchTuple:
		stitchInput = GetStitchInput(st, nodeTable, stitchTuple)
		stitchNode.ConnectToInput(stitchInput)
		return 1
	else:
		return 0

def HasStitch(dict):
	if dict.has_key("StitchTo"):
		return dict["StitchTo"]
	else:
		return 0

def GetStitchInput(st, nodeTranslator, stitchTuple):
	iInput = stitchTuple[1]
	return nodeTranslator[ stitchTuple[0] ].InputByInternalName(iInput)

def ProcessEffectDict(shaderTree,dict):
	newNodes = {}

	poserSurface = shaderTree.Node(0)

	if poserSurface.Type() != dict["Type"]:
		raise "This effect is not compatible with the selected material."

	nodesToMake = dict["NodesToMake"]
	for nodeToMake in nodesToMake.keys():
		newNodes[nodeToMake] = NodeFromDict(shaderTree, nodesToMake[nodeToMake])

	inputsToChange = dict["Settings"]
	for inputToChange in inputsToChange.keys():
		SettingsFromDict(shaderTree, shaderTree.Node(0), newNodes, inputsToChange[inputToChange])

def SettingsFromDict(shaderTree, curNode, newNodes, inputToChange):
	input = curNode.InputByInternalName(inputToChange["InternalName"])
	Stitch(shaderTree, newNodes, input, inputToChange)
	inputType = inputToChange["Type"]
	inputValue = inputToChange["Value"]
	if inputType == poser.kNodeInputCodeCOLOR:
		input.SetColor(inputValue[0],inputValue[1],inputValue[2])
	elif inputType == poser.kNodeInputCodeFLOAT or inputType == poser.kNodeInputCodeINTEGER or inputType == poser.kNodeInputCodeBOOLEAN or inputType == poser.kNodeInputCodeMENU:
		input.SetFloat(inputValue)
	elif inputType == poser.kNodeInputCodeSTRING:
		input.SetString(inputValue)
	elif inputType == poser.kNodeInputCodeVECTOR:
		input.SetColor(inputValue[0],inputValue[1],inputValue[2])
	else:
		pass #print "huh?", inputType, inputValue, type(inputValue)
	inNode = inputToChange["InNode"]
	if inNode:
		nodeName = inNode["InternalName"]
		node = newNodes[nodeName]
		node.ConnectToInput(input)
		for inputKey in inNode["Inputs"].keys():
			nodeInputDict = inNode["Inputs"][inputKey]
			SettingsFromDict(shaderTree, node, newNodes, nodeInputDict)

def NodeFromDict(shaderTree,dict):
	newNode = shaderTree.CreateNode(dict["Type"])
	newNode.SetInputsCollapsed(dict["InputsCollapsed"])
	newNode.SetPreviewCollapsed(dict["PreviewCollapsed"])
	newNode.SetLocation(dict["Location"][0],dict["Location"][1])
	return newNode

def travelNodes(node, usedNodes):
	usedNodes.append(node.InternalName())
	for inp in node.Inputs():
		inNode = inp.InNode()
		if (inNode != None):
		   travelNodes(inNode, usedNodes)

def removeExcess(mat):
	tree = mat.ShaderTree()
	root = tree.Node(0)
	usedNodes = []
	usedNodes.append(root)
	travelNodes(root, usedNodes)
	for node in tree.Nodes():
		try:
			usedNodes.index(node.InternalName())
		except:
			node.Delete()

if __name__ == "__main__":
	pass

pass
